#include <IDK.hpp>

#include <Resources.hpp>
#include <FileSystemZLib.hpp>

namespace Core
{
	void TResourceManager::Initialize(void)
	{
		mToProcess = true;
	}

	bool TResourceManager::OnUpdate(float dt)
	{
		//
		//hot loading started
		//
		if(mToProcess == false)
		{
			return false;
		}

		//iLog("TResourceManager is working");

		uint downloadableResources = 0;
		//get max loading prior
		uint maxPriority = 0;
		for(Iterator it = Begin(), end = End(); it!=end; ++it)
		{
			switch(it->GetLoadStatus())
			{
			case IDK::IResource::LoadStatus::Cancel:
				it->Cleanup();
				it->SetLoadStatus(IDK::IResource::LoadStatus::Wait);
				break;

			case IDK::IResource::LoadStatus::Loading:
				uint priority = it->GetLoadPriority();
				if(priority > maxPriority)
				{
					maxPriority = priority;
				}
				++downloadableResources;
				break;
			}
		}
		//if we haven't downloadable resources than need sleep
		if(downloadableResources == 0)
		{
			return mToProcess == false;
		}

		uint aviableResources = 0;

		for(Iterator it = Begin(), end = End(); it!=end; ++it)
		{
			switch(it->GetLoadStatus())
			{
			case IDK::IResource::LoadStatus::Loading:
				if(it->GetLoadPriority() == maxPriority)
				{
					++aviableResources;
				}
				break;
			}
		}

		//lerp dt foreach 
		//temp solution, clamped dt 0..0.5

		dt = (dt > 0.5f) ? 0.0f : dt;

		float dtForOneIteration = (((1.0f - dt) / 2.0f) / aviableResources) * 2; 

		for(Iterator it = Begin(), end = End(); it!=end; ++it)
		{
			switch(it->GetLoadStatus())
			{
			case IDK::IResource::LoadStatus::Loading:
				if(it->GetLoadPriority() == maxPriority)
				{
					it->OnLoad(dtForOneIteration);

					if(Platform::Config::ThreadSafeMode != Platform::Config::NoneThreadSafe)
					{
						Platform::Time::Sleep(static_cast<int>(dtForOneIteration * 100));
					}
				}
				break;
			}
		}

		//iLog("BackgroundQueue take job..end");
		return true;
	}

	ref<IDK::IResource> TResourceManager::AddResource(ref<IDK::IResource> resource)
	{
		return Add(resource);
	}

	ref<IDK::IStream> TResourceManager::GetStream(const String &path)
	{
		//ref<IDK::IStream> stream = new FileStream::Create(path);
		ref<IDK::IStream> stream = new FileDataStream::Create(new FileStream::Create(path));
		return stream;
	}
}